/**
 * @author Ahammer
 * @date   2009 05
 * @update 2009 08 output color options
 * @update 2011 01 added 16 bit support
 */

/*
 * This an implementation of a JAISTUFF algorithm by R.Santos
 * https://jaistuff.dev.java.net/algorithms.html
 */

/*
 * This file is part of Iqm.
 * Copyright (c) 2010-2011 Helmut Ahammer
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package op;

import jaistuff.KMeansImageClustering;
import javax.media.jai.JAI;
import javax.media.jai.ParameterBlockJAI;
import javax.media.jai.PlanarImage;

import main.Board;
import main.IqmTools;

/**
 * This is the main image processing class
 * There exist two approaches:
 * A user defined JAI operator is just called 
 * or:
 * The actual processing is implemented in this class 
 */
public class IqmKMeansOperator{ 


  public IqmKMeansOperator() {
	  //WARNING: Don't declare fields here
	  //Fields declared here aren't thread safe!   
  }
  /**
   * 
   * @param ParametrBlockJAI pb
   */
  public Object run(ParameterBlockJAI pbJAI){
	  Object ob = null;
	  //ob = JAI.create("IqmKMeans".toLowerCase(), pb, null);  
	  
	  PlanarImage pi = (PlanarImage) pbJAI.getSource(0);	
	  int    init	= pbJAI.getIntParameter("Init");
	  int    nK	    = pbJAI.getIntParameter("nK");
	  int    itMax	= pbJAI.getIntParameter("ItMax");
	  double eps    = pbJAI.getDoubleParameter("Eps");
	  int    out	= pbJAI.getIntParameter("Out");
	  	  
	  int numBands = pi.getNumBands();
	  String type = IqmTools.getImgTyp(pi);
	  double typeGreyMax = IqmTools.getImgTypeGreyMax(pi);  	
	  String imgName = (String) pi.getProperty("image_name");
	  String fileName = (String) pi.getProperty("file_name");

	  char initCh = "SDR".charAt(init);
	  //RenderingHints rh = new RenderingHints(JAI.KEY_BORDER_EXTENDER, BorderExtender.createInstance(BorderExtender.BORDER_COPY));	
	  //RenderingHints rh = null;	
	  //ParameterBlock pb = new ParameterBlock();
	  //System.out.println("I'm here1");
	  KMeansImageClustering clusterer = new KMeansImageClustering(pi, nK, itMax, eps, initCh);
	  //ob = clusterer.run();
	  clusterer.run();
	  pi = clusterer.getOutput();
	  //System.out.println("I'm here2");
	  if (out == 0) ob = pi;  //simply the calculated clusters
	  if (out == 1) {         //equidistant clusters
	
		  //piecewise histogram stretch	
		  float[][] clusterCenters = clusterer.getClusterCenters();
		  float[][][] bp = new float[numBands][2][nK];  //bp... breakpoints
		  //bp[0][0] = new float[] { 0.0F, 32.0F, 64.0F, 255.0F };
		  //bp[0][1] = new float[] { 0.0F, 128.0F, 112.0F, 255.0F };

		  for (int b = 0; b < numBands; b++){		  
			  bp[b][0][0] = clusterCenters[0][b];
			  bp[b][1][0] = 0.0f;  //new
			  //System.out.println("i, numBands    0   "  +numBands);
			  //System.out.println("clusterCenters[i][numBands-1]  "+ clusterCenters[0][numBands-1]);
			  for (int i = 1; i < nK; i++){
				  bp[b][0][i] = Math.round(clusterCenters[i][b]);
				  bp[b][1][i] = Math.round((float)((typeGreyMax+1)/(nK-1)*i));
				  //System.out.println("i, numBands    "+ i +"   "+numBands);
				  //System.out.println("bp[b][0][i]  "+ bp[b][0][i]);
				  //System.out.println("bp[b][1][i]  "+ bp[b][1][i]);
			  }
		  }
		  try {
				ob = JAI.create("piecewise", pi, bp);
		  } catch (IllegalArgumentException e) {
				//e.printStackTrace();
				Board.appendTexln("Piecewise The breakpoint abscissas must be monotonically increasing.");
				Board.appendTexln("Equidistant clusters are not possible for this image!");
				ob = pi;
		  }
		  //Achtung: "piecwise" ist nicht immer ganz exakt!!!!!!!
		  //manchmal 1,2 oder 3 anstatt 0 
		  //IqmTools.plotHistogram((PlanarImage) ob);		  
	  } 
	 ((PlanarImage)ob).setProperty("image_name", imgName);
	  ((PlanarImage)ob).setProperty("file_name", fileName);	
	  return ob;
  }
}
